from updater import Updater
from zipfile import ZipFile
from os import path
import os
from time import sleep
import time
import configparser

class Runner():
    def __init__(self) -> None:
        # 目录和服务器信息
        self.serverpath = ''
        self.localpath = ''
        self.host = ''
        self.port = ''
        self.username = 'root'
        self.password = ''
        self.ignore = ['tempfile.zip','.git','__pycache__','shot_image'] # 忽略更新的文件
        # 监听周期
        self.getinterval = 5
        self.putinterval = 5
        self.stopflag = True

    # 获取连接并保存配置
    def connect(self):
        conf = configparser.ConfigParser()
        filepath = path.join(os.getcwd(),'conf.ini')
        conf.add_section('SETTING')
        conf.set('SETTING','serverpath',self.serverpath)
        conf.set('SETTING','localpath',self.localpath)
        conf.set('SETTING','host',self.host)
        conf.set('SETTING','port',self.port)
        conf.set('SETTING','username',self.username)
        conf.set('SETTING','password',self.password)
        conf.set('SETTING','ignore',','.join(self.ignore))
        conf.set('SETTING','getinterval',str(self.getinterval))
        conf.set('SETTING','putinterval',str(self.putinterval))
        conf.write(open(filepath,'w'))
        
        # 获取一个同步实例
        self.updater = Updater(self.localpath,self.serverpath)
        return self.updater.get_connect(self.host,self.username,self.password,self.port)

    # 上传模式
    def putmode(self):
        # 迭代添加所有子文件到压缩包
        dirlist = []
        dirlist.append('./')
        # 临时压缩包
        try:
            zfile = ZipFile(path.join(self.localpath,'tempfile.zip'),'w')
            while(len(dirlist)>0):
                # 添加到压缩文件
                root_path = dirlist.pop()
                files = os.listdir(root_path)
                for file in files:
                    # 需要忽略压缩的文件列表
                    if file in self.ignore:
                        continue
                    # 写入压缩包，如果时文件夹，还要保存到队列
                    filepath = path.join(root_path,file)
                    zfile.write(filepath)
                    if path.isdir(filepath):
                        dirlist.append(filepath)
            zfile.close()
        except:
            if self.ui_signal:
                self.ui_signal.emit(f'tempfile.zip压缩失败','red')
        # 同步到服务器
        try:
            upfile = self.updater.put(path.join(self.localpath,'tempfile.zip'))
            if self.ui_signal:
                self.ui_signal.emit(f'{upfile}已上传','purple')
        except:
            if self.ui_signal:
                self.ui_signal.emit(f'{upfile}上传失败','purple')
        
    # 下载模式
    def getmode(self):
        # 下载更新文件
        updatefile = self.updater.get()
        if updatefile == '':
            return
        if self.ui_signal:
            self.ui_signal.emit(f'{updatefile}下载成功','purple')
        if not path.exists(updatefile):
            if self.ui_signal:
                self.ui_signal.emit(f'{updatefile}不存在','red')
            return
        # 覆盖解压
        try:
            zfile = ZipFile(updatefile,'r')
            zfile.extractall(path=self.localpath)
            zfile.close()
        except:
            if self.ui_signal:
                self.ui_signal.emit(f'{updatefile}解压失败','red')
            return
        print(f'{updatefile} 解压成功')
        if self.ui_signal:
            self.ui_signal.emit(f'{updatefile}解压成功','purple')
        # 删除文件
        try:
            os.remove(updatefile)
        except:
            pass

    # 下载监听器
    def getListener(self,ui_signal=None):
        # 设置启动标志位
        self.stopflag = False
        # 向UI发送消息
        self.ui_signal = ui_signal
        while(not self.stopflag):
            sleep(self.getinterval)
            self.getmode()
        print('运行停止')
        try:
            if hasattr(self.updater.transport,'close'):
                self.updater.transport.close()
        except:
            if self.ui_signal:
                self.ui_signal.emit('停止异常','black')
        if self.ui_signal:
            self.ui_signal.emit('已停止','black')
        
    # 上传监听器
    def putListener(self,ui_signal=None):
        lastfiletime = []
        # 设置启动标志位
        self.stopflag = False
        # 向UI发送消息
        self.ui_signal = ui_signal
        while(not self.stopflag):
            sleep(self.putinterval)
            files = os.listdir()
            # 检测是否要更新
            for file in files:
                if file in self.ignore:
                    continue
                # 如果文件指纹存在上一次队列中，跳过该文件
                fileinfo = file + str(path.getmtime(file))
                # 如果有变化，全部更新
                if fileinfo not in lastfiletime:
                    self.putmode()
                    break
            # 重新更新文件信息
            lastfiletime.clear()
            for file in files:
                if file in self.ignore:
                    continue
                lastfiletime.append(file + str(path.getmtime(file)))
        print('运行停止')
        try:
            if hasattr(self.updater.transport,'close'):
                self.updater.transport.close()
            if hasattr(self.updater.sftp,'close'):
                self.updater.sftp.close()
        except:
            if self.ui_signal:
                self.ui_signal.emit('停止异常','black')
        if self.ui_signal:
            self.ui_signal.emit('已停止','black')
        
    
    # 停止运行
    def stop_run(self):
        self.stopflag = True
    
    # # 在ui中运行
    # def run_on_ui(self):
    #     app = QApplication([])
    #     gui = Gui()
    #     gui.show() # 去掉ui
    #     gui.ui.pushButton_stop.setEnabled(False)
    #     app.exec_()

        

# def main():
#     runner = Runner()
#     runner.connect()
#     # 切换工作目录
#     if not path.exists(runner.localpath):
#         print(f'{runner.localpath} 目录不存在')
#         exit(0)
#     mode = input('select mode for run\n1：put mode\n2：get mode\nselect：')
#     if mode == '1':
#         print('run in put mode')
#         runner.putListener()
#     elif mode == '2':
#         print('run in get mode')
#         runner.getListener()
#     else:
#         exit(0)
    

    
    

# if __name__ == '__main__':
#     main()